package com.yb0os1;


import com.yb0os1.reject.RejectHandle;

import java.sql.SQLOutput;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

public class MyThreadPool {
    public BlockingQueue<Runnable> getTaskQueue() {
        return taskQueue;
    }

    //任务队列
    private final BlockingQueue<Runnable> taskQueue;
    //核心线程的数量
    private final int corePoolSize;
    //最大线程的数量
    private final int maxPoolSize;
    private final int keepAliveTime;
    private final TimeUnit unit;
    //拒绝策略
    private final RejectHandle rejectHandle;

    public MyThreadPool(int corePoolSize, int maxPoolSize, int keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> taskQueue,  RejectHandle rejectHandle) {
        this.corePoolSize = corePoolSize;
        this.maxPoolSize = maxPoolSize;
        this.keepAliveTime = keepAliveTime;
        this.unit = unit;
        this.taskQueue = taskQueue;
        this.rejectHandle = rejectHandle;
    }


    //核心线程
    List<Thread> coreList = new ArrayList<>();
    //非核心线程
    List<Thread> supportList = new ArrayList<>();

    //添加元素和判断长度不是原子的，所以存在线程安全问题 可以加锁 CAS等解决
    public void execute(Runnable command) {
        //目前线程列表中线程数量小于核心线程的数量，则创建线程
        if (coreList.size() < corePoolSize) {
            Thread thread = new CoreThread(command);
            coreList.add(thread);
            thread.start();
            return;
        }
        //成功添加到阻塞队列
        if (taskQueue.offer(command)) {
            return;
        }
        //任务队列也满了 需要创建非核心线程
        //核心线程满 任务队列满 但是非核心线程没有满才可以添加
        if (coreList.size() + supportList.size() < maxPoolSize) {
            Thread thread = new SupportThread(command);
            supportList.add(thread);
            thread.start();
            return;
        }

        //我们创建完线程之后 并没有处理刚才的command 不能确定是否队列真的满了
        if (!taskQueue.offer(command)) {
            //真的满 使用拒绝策略
            rejectHandle.reject(command,this);
        }
    }

    //优先处理传过来的 然后再去阻塞队列中获取
    class CoreThread extends Thread {
        private final Runnable command;

        CoreThread(Runnable command) {
            this.command = command;
        }
        @Override
        public void run() {
            command.run();
            while (true) {
                try {
                    Runnable task = taskQueue.take();
                    System.out.println("核心线程"+Thread.currentThread().getName()+"正在执行任务");
                    task.run();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            }
        }
    }

    class SupportThread extends Thread {
        private final Runnable command;

        SupportThread(Runnable command) {
            this.command = command;
        }

        @Override
        public void run() {
            command.run();
            while (true) {
                try {
                    Runnable command  = taskQueue.poll(keepAliveTime, unit);//等待一秒没有获取就会返回null
                    if (command  == null) {//线程结束
                        break;
                    }
                    command.run();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println(Thread.currentThread().getName()+"非核心线程结束");
            supportList.remove(Thread.currentThread());
//            System.out.println("当前非核心线程数量为：" + supportList.size());
        }
    }
}